//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
//------------------------------------------------------------------------------
//
//  File:    RootBus.cpp
//  Programmer: Visual.Wei (2007)
//
//  Description:   Root bus driver for s3c2443x


#include <windows.h>
#include <types.h>
#include <devload.h>
#include <ceddkex.h>
#include "Rootbus.h"
#include <CeBusCfg.h>
#include <s3c2443.h>


//------------------------------------------------------------------------------

#define DBG_ERROR       1
#define DBG_WARNING     2
#define DBG_FUNCTION    4
#define DBG_INIT        8
#define DBG_ENUM        16
#define DBG_PCMCIA      32
#define DBG_ACTIVE      64
#define DBG_TAPI        128
#define DBG_FSD         256
#define DBG_DYING       512

DBGPARAM dpCurSettings = {
                             TEXT("ROOTBUS"), {
                                 TEXT("Errors"),TEXT("Warnings"),TEXT("Functions"),TEXT("Initialization"),
                                 TEXT("Enumeration"),TEXT("PCMCIA Devices"),TEXT("Active Devices"),TEXT("TAPI stuff"),
                                 TEXT("File System Drvr"),TEXT("Dying Devs"),TEXT(""),TEXT(""),
                                 TEXT(""),TEXT(""),TEXT(""),TEXT("") },
                             DBG_ERROR | DBG_WARNING | DBG_INIT
                         };

#define ZONE_ERROR      DEBUGZONE(0)
#define ZONE_INIT       DEBUGZONE(3)
#define ZONE_ENUM       DEBUGZONE(4)


//------------------------------------------------------------------------------

extern "C" BOOL WINAPI DllEntry(HINSTANCE DllInstance, INT Reason, LPVOID Reserved)
{
	switch(Reason)
	{

	case DLL_PROCESS_ATTACH:
		RETAILREGISTERZONES(DllInstance);
		RETAILMSG(ZONE_INIT,(TEXT("RootBus.DLL DLL_PROCESS_ATTACH\r\n")));
		DisableThreadLibraryCalls((HMODULE) DllInstance);
		break;

	case DLL_PROCESS_DETACH:
		RETAILMSG(ZONE_INIT,(TEXT("RootBus.DLL DLL_PROCESS_DETACH\r\n")));
		break;
	};

	return TRUE;
}

//------------------------------------------------------------------------------

extern "C" DWORD BUS_Init (DWORD dwInfo)
{
	DefaultBusDriver * pBusDriver = new RootBus((LPCTSTR)dwInfo);

	if ( pBusDriver)
	{
		if ( pBusDriver->Init())
			return  (DWORD)pBusDriver;
		else
			delete  pBusDriver;
	}

	return NULL;
}

//------------------------------------------------------------------------------

extern "C" void BUS_Deinit (DWORD dwData)
{
	DefaultBusDriver * pBusDriver = (DefaultBusDriver*) dwData;

	if (pBusDriver != NULL)
		delete pBusDriver;
}

//------------------------------------------------------------------------------

extern "C" BOOL BUS_PowerUp(DWORD dwData)
{
	RETAILMSG(ZONE_INIT,(TEXT("RootBus.DLL : +PowerUp dwData=%x \r\n"),dwData));
	DefaultBusDriver * pBusDriver = (DefaultBusDriver * )dwData;

	if (pBusDriver)
		pBusDriver->PowerUp();

	RETAILMSG(ZONE_INIT,(TEXT("RootBus.DLL : -PowerUp dwData=%x \r\n")));

	return TRUE;
}

//------------------------------------------------------------------------------

extern "C" BOOL
	BUS_PowerDown(DWORD dwData)
{
	RETAILMSG(ZONE_INIT,(TEXT("RootBus.DLL : +PowerDown dwData=%x \r\n"),dwData));
	DefaultBusDriver * pBusDriver = (DefaultBusDriver * )dwData;

	if (pBusDriver)
		pBusDriver->PowerDown();

	RETAILMSG(ZONE_INIT,(TEXT("RootBus.DLL : -PowerDown dwData=%x \r\n")));

	return TRUE;
}

//------------------------------------------------------------------------------

#define FASTBUSACCESS_TAG 0xDEFBa51e

typedef struct __FASTBUSACCESSHANDLE
{
	DWORD dwHandleTag;
	DefaultBusDriver * pBusDriver;
	DeviceFolder     * pDeviceFolder;
}

FASTBUSACCESSHANDLE, *PFASTBUSACCESSHANDLE ;

//------------------------------------------------------------------------------

extern "C" HANDLE
	BUS_Open(HANDLE  pHead, DWORD AccessCode, DWORD   ShareMode)
{
	DefaultBusDriver * pBusDriver = (DefaultBusDriver * )pHead;

	if (pBusDriver && pBusDriver->Open(AccessCode,ShareMode))
	{
		PFASTBUSACCESSHANDLE pFastAccessHandle = new FASTBUSACCESSHANDLE;

		if (pFastAccessHandle)
		{
			pFastAccessHandle->dwHandleTag = FASTBUSACCESS_TAG;
			pFastAccessHandle->pBusDriver = pBusDriver;
			pFastAccessHandle->pDeviceFolder = NULL ;
			return (HANDLE)pFastAccessHandle;
		}
		else
			pBusDriver->Close();
	}

	return NULL;
}

//------------------------------------------------------------------------------

extern "C" BOOL
	BUS_Close(HANDLE pOpenHead)
{
	PFASTBUSACCESSHANDLE pFastAccessHandle = (PFASTBUSACCESSHANDLE) pOpenHead ;

	if (pFastAccessHandle && pFastAccessHandle->dwHandleTag ==FASTBUSACCESS_TAG )
	{
		pFastAccessHandle->pBusDriver->Close();
		delete pFastAccessHandle ;
	}

	return FALSE;
}

//------------------------------------------------------------------------------

extern "C" BOOL
	BUS_IOControl(HANDLE pOpenHead,
	              DWORD dwCode, PBYTE pBufIn,
	              DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut,
	              PDWORD pdwActualOut)
{
	PFASTBUSACCESSHANDLE pFastAccessHandle = (PFASTBUSACCESSHANDLE) pOpenHead ;

	if (pFastAccessHandle && pFastAccessHandle->dwHandleTag ==FASTBUSACCESS_TAG )
		return pFastAccessHandle->pBusDriver->FastIOControl(
		           dwCode, pBufIn, dwLenIn, pBufOut, dwLenOut, pdwActualOut,
		           &(pFastAccessHandle->pDeviceFolder)
		       );

	return FALSE;
}

//-------------------------Root Bus Driver Implementation-----------------------

RootBus::RootBus(LPCTSTR lpActiveRegPath) :
		DefaultBusDriver(lpActiveRegPath),
		m_DeviceKey(lpActiveRegPath),
		m_lpBusName(NULL)
{
	RETAILMSG(ZONE_ENUM||ZONE_INIT,(TEXT("RootBus::RootBus (ActivateRegPath=%s)\r\n"),lpActiveRegPath));

	// Get DEVLOAD_DEVKEY_VALNAME name
	m_lpActiveRegPath = NULL;
	HANDLE hThisDevice = GetDeviceHandleFromContext(lpActiveRegPath);

	if(hThisDevice != NULL)
	{
		DEVMGR_DEVICE_INFORMATION di;
		memset(&di, 0, sizeof(di));
		di.dwSize = sizeof(di);

		if(GetDeviceInformationByDeviceHandle(hThisDevice, &di))
		{
			DWORD dwKeyLen = wcslen(di.szDeviceKey) + 1;
			m_lpActiveRegPath = new TCHAR [dwKeyLen];

			if ( m_lpActiveRegPath)
			{
				wcscpy(m_lpActiveRegPath, di.szDeviceKey);
			}

			LPCWSTR pszName = wcschr(di.szBusName, L'\\');

			if(pszName != NULL)
			{
				pszName++;

				if(*pszName != 0)
				{
					dwKeyLen = wcslen(pszName) + 1;
					m_lpBusName = new TCHAR[dwKeyLen];

					if (m_lpBusName)
					{
						wcscpy(m_lpBusName, pszName);
					}
				}
			}
		}
	}

	m_lpStrInitParam = NULL;
	m_dwNumOfInitParam =0 ;
	m_dwBusNumber = 0;
	m_dwDeviceIndex = 0;

}

//------------------------------------------------------------------------------

RootBus::~RootBus()
{
	delete [] m_lpStrInitParam;
	delete [] m_lpBusName;
	delete [] m_lpActiveRegPath;
}

//------------------------------------------------------------------------------

BOOL RootBus::Open(DWORD dwAccessCode, DWORD dwShare)
{
	return TRUE;
}

//------------------------------------------------------------------------------

#define BUSNAMEUNKNOWN TEXT("P2RootBus")

BOOL RootBus::Init()
{
	BOOL  bReturn = FALSE;
	// Initialize InitParam

	if (S3c2443Clock::Init() &&  m_lpActiveRegPath==NULL)
	{
		RETAILMSG(ZONE_ENUM||ZONE_ERROR,(
		             TEXT("RootBus!Init RegOpenKeyEx() or  S3c2443Clock::Init return FALSE!!!\r\n")
		         ));
		return FALSE;
	}

	if (m_DeviceKey.IsKeyOpened() && m_lpStrInitParam == NULL )
	{
		DWORD dwKeyLen=0;
		DWORD dwType;
		LONG status=::RegQueryValueEx(m_DeviceKey.GetHKey(),DEVLOAD_REPARMS_VALNAME,NULL, &dwType,NULL,&dwKeyLen);

		if ( (status == ERROR_SUCCESS || status == ERROR_MORE_DATA)
		        && dwType== REG_MULTI_SZ && dwKeyLen!=0 )
		{
			dwKeyLen = (dwKeyLen + sizeof(TCHAR) -1 ) / sizeof(TCHAR);
			m_lpStrInitParam = new TCHAR [ dwKeyLen ];

			if (m_lpStrInitParam)
			{
				if (m_DeviceKey.GetRegValue(DEVLOAD_REPARMS_VALNAME,(LPBYTE)m_lpStrInitParam,dwKeyLen * sizeof(TCHAR)))
				{
					DWORD dwUnitCount= dwKeyLen;

					for (LPTSTR lpCurPos = m_lpStrInitParam;
					        m_dwNumOfInitParam< MAX_INITPARAM && dwUnitCount!=0 && *lpCurPos!=0 ;
					        m_dwNumOfInitParam++)
					{
						m_lpInitParamArray[m_dwNumOfInitParam] = lpCurPos;

						while (*lpCurPos!=0 && dwUnitCount!=0  )
						{
							lpCurPos++;
							dwUnitCount --;
						}

						if (dwUnitCount)
						{
							lpCurPos ++;
							dwUnitCount --;
						}
						else
							break;
					}

				}
			}
		}
	}

	// Scan And Enum All the driver in registry.
	if ( GetDeviceHandle()!=NULL &&  m_DeviceKey.IsKeyOpened())
	{
		DWORD dwKeyLen=0;

		if (!m_DeviceKey.GetRegValue(DEVLOAD_INTERFACETYPE_VALNAME,(PUCHAR) &m_dwBusType,sizeof(m_dwBusType)))
		{
			// No interface type defined
			m_dwBusType=InterfaceTypeUndefined;
		};

		if (!m_DeviceKey.GetRegValue(DEVLOAD_BUSNUMBER_VALNAME , (LPBYTE)&m_dwBusNumber,sizeof(m_dwBusNumber)))
			m_dwBusNumber=0;

		if ( AssignChildDriver() )
			return TRUE;
	};

	RETAILMSG(ZONE_ENUM|ZONE_ERROR,(TEXT("-RootBus!Init return FALSE!!!\r\n")));

	return FALSE;

};

//------------------------------------------------------------------------------

BOOL RootBus::PostInit()
{
	BOOL bReturn = FALSE;

	if ( GetDeviceHandle()!=NULL &&  m_DeviceKey.IsKeyOpened())
	{
		bReturn=ActivateAllChildDrivers();
	}

	return bReturn;
}
//------------------------------------------------------------------------------
BOOL RootBus::PowerUp() 
{
	return S3c2443Clock::PowerUp();
};
//------------------------------------------------------------------------------
BOOL RootBus::PowerDown()
{
	return S3c2443Clock::PowerDown();
};
//------------------------------------------------------------------------------

BOOL RootBus::AssignChildDriver()
{
	DWORD NumSubKeys;
	DWORD MaxSubKeyLen;
	DWORD MaxClassLen;
	DWORD NumValues;
	DWORD MaxValueNameLen;
	DWORD MaxValueLen;
	// Get info on Template Key
	BOOL bSuccess = m_DeviceKey.RegQueryInfoKey(
	                    NULL,               // class name buffer (lpszClass)
	                    NULL,               // ptr to length of class name buffer (lpcchClass)
	                    NULL,               // reserved
	                    &NumSubKeys,        // ptr to number of sub-keys (lpcSubKeys)
	                    &MaxSubKeyLen,      // ptr to longest subkey name length (lpcchMaxSubKeyLen)
	                    &MaxClassLen,       // ptr to longest class string length (lpcchMaxClassLen)
	                    &NumValues,         // ptr to number of value entries (lpcValues)
	                    &MaxValueNameLen,  // ptr to longest value name length (lpcchMaxValueNameLen)
	                    &MaxValueLen,       // ptr to longest value data length (lpcbMaxValueData)
	                    NULL,               // ptr to security descriptor length
	                    NULL);              // ptr to last write time

	if (!bSuccess)
	{
		RETAILMSG(ZONE_ENUM|ZONE_ERROR,
		         (TEXT("RootBus::RegCopyKey RegQueryInfoKey returned fails.\r\n")));
		return FALSE;
	}

	// Recurse for each sub-key

	for (DWORD Key = 0; Key < NumSubKeys; Key++)
	{
		// Get TKey sub-key according to Key
		WCHAR ValName[DEVKEY_LEN];
		DWORD ValLen = sizeof(ValName) / sizeof(WCHAR);

		if (! m_DeviceKey.RegEnumKeyEx(  Key, ValName, &ValLen, NULL,  NULL,  NULL, NULL))
		{
			RETAILMSG(ZONE_ENUM,
			         (TEXT("RootBus::RegCopyKey RegEnumKeyEx(%d) returned Error\r\n"), ValName));
			break;
		}
		else
		{
			// Open sub-key under TKey
			CRegistryEdit TSubKey(m_DeviceKey.GetHKey(),ValName);

			if (!TSubKey.IsKeyOpened())
			{
				RETAILMSG(ZONE_ENUM|ZONE_ERROR,
				         (TEXT("RootBus::RegCopyKey RegOpenKeyEx(%s) returned Error\r\n"), ValName));

				continue;
			}
			else
			{ // Get Bus Info.
				DeviceFolder * nDevice = CreateNewDevice(TSubKey,ValName) ;

				if (nDevice && nDevice->Init())
				{
					InsertChild(nDevice);
				}
				else
				{
					ASSERT(FALSE);

					if (nDevice)
						delete nDevice;
				}
			}

		}
	}

	return TRUE;
}

//------------------------------------------------------------------------------

DWORD RootBus::GetBusNamePrefix(__out_ecount(dwSizeInUnit) LPTSTR lpReturnBusName,DWORD dwSizeInUnit)
{
	if ( lpReturnBusName &&  dwSizeInUnit)
	{
		LPCTSTR lpBusName = (m_lpBusName!=NULL?m_lpBusName:BUSNAMEUNKNOWN);
		DWORD dwCopyUnit = min(_tcslen(lpBusName) +1 , dwSizeInUnit);
		_tcsncpy(lpReturnBusName,lpBusName,dwCopyUnit);
		lpReturnBusName[dwCopyUnit-1]=0;
		return dwCopyUnit;
	}
	else
		return 0;
}

//------------------------------------------------------------------------------

#define MAX_TEMP_BUFFER_SIZE 0x200
BOOL RootBus::ActivateAllChildDrivers()
{
	TakeReadLock();
	DeviceFolder * pCurDevice = GetDeviceList ();

	while (pCurDevice)
	{
		RETAILMSG(ZONE_ENUM,(TEXT("ActivateChild: reg path is %s\r\n"),pCurDevice->GetRegPath()));
		// Create Initial Active Registry.

		for (DWORD dwIndex=0; dwIndex< m_dwNumOfInitParam; dwIndex++)
		{
			BYTE tempBuffer[ MAX_TEMP_BUFFER_SIZE] ;
			DWORD dwSize=MAX_TEMP_BUFFER_SIZE;
			DWORD dwType;

			if (m_DeviceKey.IsKeyOpened() &&
			        m_DeviceKey.RegQueryValueEx(m_lpInitParamArray[dwIndex],&dwType, tempBuffer,&dwSize) )
			{
				REGINI Reg;
				Reg.lpszVal = m_lpInitParamArray[dwIndex];
				Reg.dwType = dwType;
				Reg.dwLen = dwSize;
				Reg.pData = tempBuffer;
				pCurDevice->AddInitReg(1, &Reg);
				RETAILMSG(ZONE_ENUM,(TEXT("ActivateChild add %s to %s ActivePath\r\n"),m_lpInitParamArray[dwIndex],pCurDevice->GetRegPath()));
			}
		}

		pCurDevice = pCurDevice->GetNextDeviceFolder();
	}

	// Activate Device
	DWORD dwCurOrder = 0;

	while (dwCurOrder != MAXDWORD)
	{
		RETAILMSG(ZONE_ENUM,(TEXT(" RootBus::ActivateChild load device driver at order 0x%x \r\n"),dwCurOrder));
		DWORD dwNextOrder = MAXDWORD;
		pCurDevice = GetDeviceList ();

		while (pCurDevice)
		{
			DWORD dwDeviceLoadOrder = pCurDevice->GetLoadOrder();

			if ( dwDeviceLoadOrder == dwCurOrder)
				pCurDevice->LoadDevice();
			else
				if (dwDeviceLoadOrder> dwCurOrder  && dwDeviceLoadOrder < dwNextOrder)
					dwNextOrder = dwDeviceLoadOrder;

			pCurDevice = pCurDevice->GetNextDeviceFolder();
		}

		dwCurOrder = dwNextOrder;
	}

	LeaveReadLock();
	return TRUE;
}

//------------------------------------------------------------------------------

S3c2443DeviceFolder * RootBus::CreateNewDevice(CRegistryEdit& TSubKey,LPCTSTR lpName )
{
	DDKPCIINFO dpi; // Here PCI infomation means bus-agnostic bus information
	PREFAST_ASSERT(lpName!=NULL);
	dpi.cbSize = sizeof (DDKPCIINFO);
	dpi.dwDeviceNumber = (DWORD)-1;
	dpi.dwFunctionNumber = (DWORD)-1;

	if (TSubKey.GetPciInfo(&dpi)!=ERROR_SUCCESS || dpi.dwDeviceNumber == (DWORD)-1 || dpi.dwFunctionNumber == (DWORD)-1)
	{
		dpi.dwDeviceNumber = m_dwDeviceIndex++;
		dpi.dwFunctionNumber = 0;
	}

	DDKWINDOWINFO dwi;// Here bus-agnostic register windows information

	if (TSubKey.GetWindowInfo(&dwi)!=ERROR_SUCCESS)
	{
		dwi.dwNumIoWindows = 0;
		dwi.dwNumMemWindows = 0 ;
		dwi.dwBusNumber = (DWORD) -1 ;
	}

	// We Create Foler for this driver.
	TCHAR lpChildPath[DEVKEY_LEN];

	_tcsncpy(lpChildPath,m_lpActiveRegPath,DEVKEY_LEN-1);

	lpChildPath[DEVKEY_LEN-2] = 0;

	DWORD dwLen=_tcslen(lpChildPath);

	lpChildPath[dwLen]=_T('\\');

	dwLen++;

	lpChildPath[dwLen]=0;

	_tcsncat(lpChildPath,lpName,DEVKEY_LEN-1-dwLen);

	lpChildPath[DEVKEY_LEN-1]=0;

	LPCTSTR lpBusName = (m_lpBusName!=NULL?m_lpBusName:BUSNAMEUNKNOWN);

	if (dwi.dwNumMemWindows == 0)
	{
		return new S3c2443DeviceFolder(
		           lpBusName, lpChildPath, m_dwBusType, dwi.dwBusNumber,
		           dpi.dwDeviceNumber, dpi.dwFunctionNumber, GetDeviceHandle(),
		           NULL, this
		       );
	}
	else
	{
		S3c2443DeviceFolder * pDevice = NULL;


		switch (dwi.memWindows[0].dwBase)
		{
		case S3C2443_BASE_REG_PA_CAM:
		//case S3C2443_BASE_REG_PA_PWM:
		case S3C2443_BASE_REG_PA_UART0:			
		case S3C2443_BASE_REG_PA_UART1:
		case S3C2443_BASE_REG_PA_UART2:
		case S3C2443_BASE_REG_PA_UART3:
		case S3C2443_BASE_REG_PA_AC97:
		case S3C2443_BASE_REG_PA_SDI:
		case S3C2443_BASE_REG_PA_USBD:			
		//case S3C2443_BASE_REG_PA_HSMMC:			
			pDevice = new S3c2443OneClockFolder(
			              lpBusName, lpChildPath, m_dwBusType, dwi.dwBusNumber,
			              dpi.dwDeviceNumber, dpi.dwFunctionNumber, GetDeviceHandle(),
			              &dwi, this);
			break;

		case S3C2443_BASE_REG_PA_USB:		
			pDevice = new S3c2443TwoClocksFolder(
			              lpBusName, lpChildPath, m_dwBusType, dwi.dwBusNumber,
			              dpi.dwDeviceNumber, dpi.dwFunctionNumber, GetDeviceHandle(),
			              &dwi, this
			          );
			break;
#if 0
		case OMAP730_OTG_REGS_PA:

		case OMAP730_USBD_REGS_PA:

		case OMAP730_USBH_REGS_PA:
			pDevice = new OMAP730ThreeClocksFolder(
			              lpBusName, lpChildPath, m_dwBusType, dwi.dwBusNumber,
			              dpi.dwDeviceNumber, dpi.dwFunctionNumber, GetDeviceHandle(),
			              &dwi, this
			          );
			break;
#endif
		default:
			pDevice = new S3c2443DeviceFolder(
			              lpBusName, lpChildPath, m_dwBusType, dwi.dwBusNumber,
			              dpi.dwDeviceNumber, dpi.dwFunctionNumber, GetDeviceHandle(),
			              &dwi, this
			          );
			break;
		}


		return pDevice;
	}
}

//------------------------------------------------------------------------------

BOOL RootBus::FastIOControl(
    DWORD dwCode, PBYTE pBufIn, DWORD dwLenIn, PBYTE pBufOut,
    DWORD dwLenOut, PDWORD pdwActualOut, DeviceFolder **ppDeviceFolder
)
{
	BOOL rc = FALSE;
	CEDEVICE_POWER_STATE dx;

	switch (dwCode)
	{
#if 1

	case IOCTL_DISPLAY_SETDEVICEPOWERSTATE:
		// Caller must be trusted

		if (CeGetCallerTrust() != OEM_CERTIFY_TRUST)
		{
			RETAILMSG(ZONE_ERROR, (L"ERROR: RootBus::FastIOControl: "
			                      L"Caller is untrused\r\n"
			                     ));
			SetLastError(ERROR_ACCESS_DENIED);
			break;
		}

		if (!CeSafeCopyMemory(&dx, pBufIn, sizeof(dx)))
		{
			SetLastError(ERROR_INVALID_PARAMETER);
			break;
		}

		switch (dx)
		{

		case D0:

		case D1:

		case D2:
			rc = RequestClock(CLK_CLOCK_LCD);
			break;

		case D3:

		case D4:
			rc = ReleaseClock(CLK_CLOCK_LCD);
			break;
		}

		break;
#endif

	default:
		rc = DefaultBusDriver::FastIOControl(
		         dwCode, pBufIn, dwLenIn, pBufOut, dwLenOut, pdwActualOut,
		         ppDeviceFolder
		     );
	}

	return rc;
}

//---------------Individual Device Power Module Implementation------------------

BOOL S3c2443DeviceFolder::UpdatePowerState()
{
	return TRUE;
}


//------------------------------------------------------------------------------

BOOL S3c2443OneClockFolder::UpdatePowerState()
{
	switch (m_CurActualPowerState)
	{

	case D0:

	case D1:

	case D2:
		ClkRequest(CLOCK_ALLOCATION_ID_REGISTER_ACCESS);
		break;
	}

	switch (m_CurActualPowerState)
	{

	case D3:

	case D4:
		ClkRelease(CLOCK_ALLOCATION_ID_REGISTER_ACCESS);
	}

	return TRUE;
}

//------------------------------------------------------------------------------

BOOL S3c2443TwoClocksFolder::UpdatePowerState()
{
	switch (m_CurActualPowerState)
	{

	case D0:

	case D1:
		ClkRequest(CLOCK_ALLOCATION_ID_OPERATION);
		ClkRequest(CLOCK_ALLOCATION_ID_REGISTER_ACCESS);
		break;

	case D2:
		ClkRelease(CLOCK_ALLOCATION_ID_OPERATION);
		ClkRequest(CLOCK_ALLOCATION_ID_REGISTER_ACCESS);
		break;
	}

	switch (m_CurActualPowerState)
	{

	case D3:

	case D4:
		ClkRelease(CLOCK_ALLOCATION_ID_OPERATION);
		ClkRelease(CLOCK_ALLOCATION_ID_REGISTER_ACCESS);
	}

	return TRUE;
}

//------------------------------------------------------------------------------

BOOL S3c2443ThreeClocksFolder::UpdatePowerState()
{
	switch (m_CurActualPowerState)
	{

	case D0:

	case D1:
		ClkRequest(CLOCK_ALLOCATION_ID_OPERATION);
		ClkRequest(CLOCK_ALLOCATION_ID_REGISTER_ACCESS);
		ClkRequest(CLOCK_ALLOCATION_OTHER);
		break;

	case D2:
		ClkRequest(CLOCK_ALLOCATION_ID_REGISTER_ACCESS);
		ClkRelease(CLOCK_ALLOCATION_ID_OPERATION);
		ClkRelease(CLOCK_ALLOCATION_OTHER);
		break;
	}

	switch (m_CurActualPowerState)
	{

	case D3:

	case D4:
		ClkRelease(CLOCK_ALLOCATION_ID_OPERATION);
		ClkRelease(CLOCK_ALLOCATION_ID_REGISTER_ACCESS);
		ClkRelease(CLOCK_ALLOCATION_OTHER);
	}

	return TRUE;
}

//------------------------------------------------------------------------------

